#pragma once
#include <string>
#include <fstream>
#include <sstream>

#include "json.hpp"

#define JSON_REFLECTION NLOHMANN_DEFINE_TYPE_INTRUSIVE

namespace cpp
{
	template<class T>
	std::string object2Str(T&& obj)
	{
		nlohmann::json json_disp;
		nlohmann::to_json(json_disp, obj);
		std::stringstream ss;
		ss << json_disp.dump(4);
		return ss.str();
	}

	template<class T>
	bool string2Object(const std::string& json_str, T& obj)
	{
		try
		{
			nlohmann::json json_obj;
			json_obj = nlohmann::json::parse(json_str, nullptr, false);
			nlohmann::from_json(json_obj, obj);
			return true;
		}
		catch (const std::exception& e)
		{
			return false;
		}
	}

	template<class T>
	void printObject(T&& obj)
	{
		nlohmann::json json_disp;
		nlohmann::to_json(json_disp, obj);
		printf("Data: %s\n", json_disp.dump(4).c_str());
	}

	template<class T>
	bool loadJsonFileToObject(const std::string& file_json, T&& obj)
	{
		std::ifstream ifile(file_json);
		if (!ifile.good()) return false;
		try
		{
			nlohmann::json json_obj;
			ifile >> json_obj;
			nlohmann::from_json(json_obj, obj);
		}
		catch (const std::exception& e)
		{
			printf("load failed: %s\n", e.what());
			return false;
		}
		return true;
	}

	template<class T>
	bool saveObjectToJsonFile(const std::string& file_json, T&& obj)
	{
		std::ofstream ofile(file_json);
		if (!ofile.good()) return false;
		nlohmann::json json_obj;
		nlohmann::to_json(json_obj, obj);
		ofile << json_obj.dump(4) << std::endl;
		return true;
	}
}
